<?php

	$n2f = n2f_cls::getInstance();
	$n2f->registerExtension(
		'n2f_router',
		'N2F URL Routing',
		'0.1',
		'Chris Butcher',
		'http://www.zibings.com'
	);

	$n2f->hookEvent(N2F_EVT_CORE_INIT, 'init_router');

	/**
	 * Called using the array_filter function, in order to remove empty
	 * indexes from an array.
	 *
	 * @example $arr = array_filter($arr, 'removeEmptyIndexes');
	 *
	 * @param $var
	 *
	 * @return mixed
	 */
	function removeEmptyIndexes($var) {
		if( !$var || empty($var) )
			return;
		else return $var;
	}

	/**
	 * Extract the directory structure from the requested URI, check whether there
	 * is a route that exists, and then load that route.
	 *
	 * @param n2f_cls $n2f
	 */
	function init_router($n2f) {

		if( isset($_REQUEST['_n2froute']) ){

			$urlStructure = explode('/', $_REQUEST['_n2froute']);
			unset($_REQUEST['_n2froute']);

			$urlStructure = array_filter($urlStructure, 'removeEmptyIndexes');

			if(count($urlStructure) > 0){

				// The first index in the urlStructure should be the module which we are loading.
				// This is where we check to see if there is a route for that module.
				if( isset(n2f_router::$routes[$urlStructure[0]]) || is_null(n2f_router::$routes[$urlStructure[0]]) ){
					$_REQUEST['nmod'] = $urlStructure[0];

					$route = n2f_router::$routes[$urlStructure[0]];
					$params = $route['parameters'];

					$urlQueryString = array_slice($urlStructure, 1, count($urlStructure));

					// We start by rotating through the routes query parameters
					if( is_array($params) && count($params) > 0 ){
						$keys = array_keys($params);
						for($i = 0; $i < count($params); $i++) {

							// Then we check to see if the user has supplied the query parameter
							if( isset($keys[$i]) && isset($urlQueryString[$i]) ){
								$_REQUEST[$keys[$i]] = $urlQueryString[$i];

							// Otherwise, if the user didn't supply the query parameter,
							// we use any default value that was given.
							} else {
								if( isset($params[$keys[$i]]) ){
									$_REQUEST[$keys[$i]] = $params[$keys[$i]];
								}
							}
						}
					}

					// Execute any callback which this route has.
					if( is_callable($route['callback'], true, $methodName) ) {
						$_REQUEST = call_user_func($route['callback'], $route, $_REQUEST);
					}
				}
			}
		}
	}

	class n2f_router {

		/**
		 * @var array
		 */
		public static $routes;

		/**
		 * Add a route to the router.
		 *
		 * @param string $module
		 * @param array|string|null $parameters
		 * @param string|array $callback
		 *
		 * @return bool
		 */
		public static function create($module, $parameters = null, $callback = null) {
			if( is_null($module) || empty($module) )
				return false;

			if( is_string($parameters) ) {
				$parameters = n2f_router::parseParamString($parameters);
			}

			self::$routes[$module] = array(
				'module' => $module,
				'parameters' => $parameters,
				'callback' => $callback
			);

			return true;
		}

		public static function generateUrl($module, $params = array()) {
			$n2f = n2f_cls::getInstance();

			/*
			 * TODO: If the site configuration doesn't have the domain name setup,
			 * TODO: then find another way to resolve the domain name.
			 */
			if( empty($n2f->cfg->site->domain) )
				return null;

			$domain = $n2f->cfg->site->domain;
			if( $domain[count($domain)-1] == '/')
				$domain = rtrim($domain, '/');

			return $domain.'/'.$module.'/'.implode('/', $params);
		}

		/**
		 * Break apart the route query string and set any default
		 * values that it might contain.
		 *
		 * @param $string
		 *
		 * @return array
		 */
		public static function parseParamString($string) {
			$replacements  = array();
			$rplcments 	= explode('/', $string);

			foreach($rplcments as $key => $value) {
				if( stristr($value, ':') ) {
					$vars = explode(':', $value);
					if( count($vars) == 2 ){
						$replacements[$vars[0]] = $vars[1];
					}
				}
			}

			return $replacements;
		}
	}
?>